package com.synjones.hymodule;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * 原始图像数组转bmp
 * @ClassName Bytes2Bmp
 * @author zhaodianbo@Synjones
 * @date 2015-10-10 下午4:12:06
 *
 */
public class Bytes2Bmp {
	static byte[] color_table;
	static byte[] infos;
	static byte[] header;
	static int lastH;
	static int lastW;
	public static byte[] genBmp(int w,int h,byte pixels[]){
		byte[]	rgb = addBMP_8(pixels, w, h);                         //排列图像数据成bmp要求格式
		if(color_table==null|| lastH!=h || lastW!=w)
			color_table = addBMPImageInfosHeaderTable(w, h);          //颜色表，8位图必须有
		if(infos==null || lastH!=h || lastW!=w)
			infos = addBMPImageInfosHeader(w, h);                     //文件信息头
		if(header==null || lastH!=h || lastW!=w)
			header = addBMPImageHeader(rgb.length, infos.length + color_table.length);  //文件头
		byte[] buffer = new byte[header.length + infos.length + color_table.length
				+ rgb.length];                                   //申请用来组合上面四个部分的空间，这个空间直接保存就是bmp图了
		System.arraycopy(header, 0, buffer, 0, header.length);           //复制文件头
		System.arraycopy(infos, 0, buffer, header.length, infos.length); //复制文件信息头
		System.arraycopy(color_table, 0, buffer, header.length + infos.length,
				color_table.length);                             //复制颜色表
		System.arraycopy(rgb, 0, buffer, header.length + infos.length +
				color_table.length, rgb.length);                 //复制真正的图像数据
		lastW=w;
		lastH=h;
		return buffer;
	}

	public static Bitmap genBitmap(int w,int h,byte pixels[]){
		byte[]img= genBmp( w, h, pixels);
		if(img==null) return null;
		Bitmap bmpBitmap=BitmapFactory.decodeByteArray(img, 0, img.length);
		return bmpBitmap;
	}

	public static void save2BMPFile(int w,int h,byte pixels[],String path){
		byte[]img= genBmp( w, h, pixels);
		if(img==null) return;
		if(path!=null && !path.isEmpty())
			com.synjones.hymodule.Bytes2Bmp.testWriteFile(img,path);
	}

	public static void testWriteFile(byte[]data,String filePath){

		File fingerPhotoFile = new File(filePath);
		try {
			FileOutputStream fos = new FileOutputStream(fingerPhotoFile);
			fos.write(data);
			fos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	private static byte[] addBMPImageHeader(int size, int lenH) {
		byte[] buffer = new byte[14];
		int m_lenH = lenH + buffer.length;      //lenH:文件信息头
		//和颜色表长度之和
		size += m_lenH;     //size:颜色数据的长度+两个文件头长度+颜色表长度
		buffer[0] = 0x42;   //WORD 固定为0x4D42;
		buffer[1] = 0x4D;
		buffer[2] = (byte) (size >> 0);    //DWORD 文件大小
		buffer[3] = (byte) (size >> 8);
		buffer[4] = (byte) (size >> 16);
		buffer[5] = (byte) (size >> 24);
		buffer[6] = 0x00;    //WORD 保留字，不考虑
		buffer[7] = 0x00;
		buffer[8] = 0x00;    //WORD 保留字，不考虑
		buffer[9] = 0x00;
		buffer[10] = (byte) (m_lenH >> 0);      //DWORD 实际位图数据的偏移字
		buffer[11] = (byte) (m_lenH >> 8);      //节数，即所有三个头（文件头、
		buffer[12] = (byte) (m_lenH >> 16);     //文件信息头、颜色表）之和
		buffer[13] = (byte) (m_lenH >> 24);     //14 + 40 + 1024 = 1078
		//0x0436   0x0036=40+14=54
		return buffer;
	}



	private static byte[] addBMPImageInfosHeader(int w, int h) {
		byte[] buffer = new byte[40];
		int ll = buffer.length;
		buffer[0] = (byte) (ll >> 0);    //DWORD：本段头长度：40   0x0028
		buffer[1] = (byte) (ll >> 8);
		buffer[2] = (byte) (ll >> 16);
		buffer[3] = (byte) (ll >> 24);
		buffer[4] = (byte) (w >> 0);    //long：图片宽度
		buffer[5] = (byte) (w >> 8);
		buffer[6] = (byte) (w >> 16);
		buffer[7] = (byte) (w >> 24);
		buffer[8] = (byte) (h >> 0);    //long：图片高度
		buffer[9] = (byte) (h >> 8);
		buffer[10] = (byte) (h >> 16);
		buffer[11] = (byte) (h >> 24);
		buffer[12] = 0x01;           //WORD:平面数：1
		buffer[13] = 0x00;
		buffer[14] = 0x08;           //WORD:图像位数：8位
		buffer[15] = 0x00;
		buffer[16] = 0x00;           //DWORD：压缩方式，可以是0，1，2，
		buffer[17] = 0x00;           //其中0表示不压缩
		buffer[18] = 0x00;
		buffer[19] = 0x00;
		buffer[20] = 0x00;           //DWORD；实际位图数据占用的字节数,当上一个数值
		buffer[21] = 0x00;           //biCompression等于0时，这里的值可以省略不填
		buffer[22] = 0x00;
		buffer[23] = 0x00;
		buffer[24] = (byte) 0x20;    //LONG：X方向分辨率
		buffer[25] = 0x4E;           //20000(0x4E20) dpm  1 in = 0.0254 m
		buffer[26] = 0x00;
		buffer[27] = 0x00;
		buffer[28] = (byte) 0x20;    //LONG：Y方向分辨率
		buffer[29] = 0x4E;           //20000(0x4E20) dpm  1 in = 0.0254 m
		buffer[30] = 0x00;
		buffer[31] = 0x00;
		buffer[32] = 0x00;           //DWORD：使用的颜色数，如果为0，
		buffer[33] = 0x00;           //则表示默认值(2^颜色位数)
		buffer[34] = 0x00;
		buffer[35] = 0x00;
		buffer[36] = 0x00;           //DWORD：重要颜色数，如果为0,
		buffer[37] = 0x00;           //则表示所有颜色都是重要的
		buffer[38] = 0x00;
		buffer[39] = 0x00;

		return buffer;
	}



	private static byte[] addBMPImageInfosHeaderTable(int w, int h) {
		byte[] buffer = new byte[256 * 4];

		//生成颜色表
		for (int iiii = 0; iiii < 256; iiii++) {
			buffer[0 + 4 * iiii] = (byte) iiii;   //Blue
			buffer[1 + 4 * iiii] = (byte) iiii;   //Green
			buffer[2 + 4 * iiii] = (byte) iiii;   //Red
			buffer[3 + 4 * iiii] = (byte) 0xFF;   //保留值
		}

		return buffer;
	}



	private static byte[] addBMP_8(byte[] b, int w, int h) {
		int len = w*h; //b.length;
		System.out.println(b.length);
		byte[] buffer = new byte[w * h];
		int offset = 0;
		for (int i = len - 1; i >= (w - 1); i -= w) {
			// 对于bmp图，DIB文件格式最后一行为第一行，每行按从左到右顺序
			int end = i, start = i - w + 1;
			for (int j = start; j <= end; j++) {
				buffer[offset] = b[j];
				offset ++;
			}
		}
		return buffer;
	}


	
	
	/*private  void writeBmpHead(OutputStream out,int width,int height) throws IOException {
		LittleEndianDataOutput out1 = new LittleEndianDataOutput(out);
		int rowSize = (width * 3 + 3) / 4 * 4;  // 3 bytes per pixel in RGB888, round up to multiple of 4
		int imageSize = rowSize * height;
		
		// BITMAPFILEHEADER
		out1.writeBytes(new byte[]{'B', 'M'});  // FileType
		out1.writeInt32(14 + 40 + imageSize);   // FileSize
		out1.writeInt16(0);                     // Reserved1
		out1.writeInt16(0);                     // Reserved2
		out1.writeInt32(14 + 40);               // BitmapOffset
		
		// BITMAPINFOHEADER
		out1.writeInt32(40);                        // Size
		out1.writeInt32(width);                     // Width
		out1.writeInt32(height);                    // Height
		out1.writeInt16(1);                         // Planes
		out1.writeInt16(8);                        // BitsPerPixel
		out1.writeInt32(0);                         // Compression
		out1.writeInt32(imageSize);                 // SizeOfBitmap
		out1.writeInt32(bmp.horizontalResolution);  // HorzResolution
		out1.writeInt32(bmp.verticalResolution);    // VertResolution
		out1.writeInt32(0);                         // ColorsUsed
		out1.writeInt32(0);                         // ColorsImportant
		
		// Image data
		byte[] row = new byte[rowSize];
		for (int y = height - 1; y >= 0; y--) {
			for (int x = 0; x < width; x++) {
				int color = image.getRgb888Pixel(x, y);
				row[x * 3 + 0] = (byte)(color >>>  0);  // Blue
				row[x * 3 + 1] = (byte)(color >>>  8);  // Green
				row[x * 3 + 2] = (byte)(color >>> 16);  // Red
			}
			out1.writeBytes(row);
		}
		
		out1.flush();
	}
	*/
}
